package com.bjy.qa.exception;

import com.auth0.jwt.exceptions.*;
import com.bjy.qa.entity.Response;
import com.bjy.qa.enumtype.ErrorCode;
import org.springframework.context.annotation.Configuration;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.sql.SQLException;
import java.sql.SQLSyntaxErrorException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

@Configuration
@ControllerAdvice
@ResponseBody
public class GlobalException {

    @ExceptionHandler(SignatureVerificationException.class)
    public Object jwtExceptionHandler(SignatureVerificationException e) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("errorMsg", "无效签名。" + e.getMessage());
        return Response.fail(ErrorCode.TOKEN_EXCEPTION, map);
    }

    @ExceptionHandler(TokenExpiredException.class)
    public Object jwtExceptionHandler(TokenExpiredException e) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("errorMsg", "token过期。" + e.getMessage());
        return Response.fail(ErrorCode.TOKEN_EXCEPTION, map);
    }

    @ExceptionHandler(AlgorithmMismatchException.class)
    public Object jwtExceptionHandler(AlgorithmMismatchException e) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("errorMsg", "加密算法不一致。" + e.getMessage());
        return Response.fail(ErrorCode.TOKEN_EXCEPTION, map);
    }

    @ExceptionHandler(JWTDecodeException.class)
    public Object jwtExceptionHandler(JWTDecodeException e) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("errorMsg", "解码 JWT 公共信息错误。");
        return Response.fail(ErrorCode.TOKEN_EXCEPTION, map);
    }

    @ExceptionHandler(InvalidClaimException.class)
    public Object jwtExceptionHandler(InvalidClaimException e) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("errorMsg", "校验claims内容不匹配。" + e.getMessage());
        return Response.fail(ErrorCode.TOKEN_EXCEPTION, map);
    }

    @ExceptionHandler({SQLException.class, SQLSyntaxErrorException.class, DataIntegrityViolationException.class, BadSqlGrammarException.class})
    public Object badSqlGrammarExceptionHandler(Exception e) {
        e.printStackTrace();
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("errorMsg", "数据库操作失败！" + e.getClass());
        return Response.fail(map);
    }

    @ExceptionHandler(MyException.class)
    public Object myExceptionHandler(MyException e) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("errorMsg", e.getMessage());
        return Response.fail(map);
    }

    @ExceptionHandler(Exception.class)
    public Object exceptionHandler(Exception e) {
        e.printStackTrace();
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("errorMsg", e.getMessage());
        return Response.fail(map);
    }

    /*
     * 捕获实体类定义校验规则引发的异常处理
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Object validateExceptionHandler(MethodArgumentNotValidException ex) {
        List<String> errorList = new LinkedList<>();
        List<ObjectError> errors = ex.getBindingResult().getAllErrors();
        for (ObjectError objectError : errors) {
            errorList.add(objectError.getDefaultMessage());
        }

        Map<String, Object> map = new HashMap<String, Object>();
        map.put("errorList", errorList);
        return Response.fail(ErrorCode.ARGUMENT_NOT_VALID, map);
    }

    /*
     * 捕获controller中定义校验规则引发的异常处理
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public Object controllerExceptionHandler(ConstraintViolationException ex) {
        List<String> errorList = new LinkedList<>();
        for (ConstraintViolation<?> constraintViolation : ex.getConstraintViolations()) {
            errorList.add(constraintViolation.getMessage());
        }

        Map<String, Object> map = new HashMap<String, Object>();
        map.put("errorList", errorList);
        return Response.fail(ErrorCode.ARGUMENT_NOT_VALID, map);
    }
}


